package com.acme.bankapp.domain.email.impl;

import java.util.LinkedList;
import java.util.List;

import com.acme.bankapp.domain.email.Email;
import com.acme.bankapp.domain.email.Queue;
import com.acme.bankapp.domain.exceptions.EmptyEmailBoxException;
import com.acme.bankapp.domain.exceptions.MailCantBeAdded;

public class QueueImpl implements Queue {

	private List<Email> mails = new LinkedList<Email>();
	private Object monitor = new Object();
	private final int maxMailBoxSize;
	private boolean isClosed = false;

	public QueueImpl(int mailBoxSize) {
		maxMailBoxSize = mailBoxSize;
	}

	public void addEmail(Email email) throws MailCantBeAdded {

		synchronized (monitor) {
			System.out.println("in addEmail 1");
			while (mails.size() == maxMailBoxSize) {
				try {
					System.out.println("in addEmail 2");
					monitor.wait();
					if (isClosed) {
						throw new InterruptedException();
					}
				} catch (InterruptedException e) {
					if (mails.size() == maxMailBoxSize)
						throw new MailCantBeAdded();
					else
						break;
				}
			}
			System.out.println("in addEmail 3");
			mails.add(email);
			monitor.notify();
			System.out.println("in addEmail after notify");
		}

	}

	public Email getEmail() throws EmptyEmailBoxException {
		synchronized (monitor) {

			System.out.println("in getEmail 1");
			while (mails.isEmpty()) {
				try {
					mails.wait();
					if (isClosed) {
						throw new InterruptedException();
					}
				} catch (InterruptedException e) {
					if (mails.isEmpty())
						throw new EmptyEmailBoxException();
					else
						break;
				}
			}

			return mails.remove(0);
		}
	}

	public void close() {
		isClosed = true;
		monitor.notify();
	}
	
	public boolean isClosed () {
		return isClosed;
	}

}
